package com.cpr.core.nio.selector;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

/**
 * @author Chen Panrui
 * created at 2021/12/23 15:37
 */
public class NioSelectorServer {

    public static void main(String[] args) throws IOException {
        // 1、打开一个通道 服务端的nio的Socket
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress("127.0.0.1",8888));
        serverSocketChannel.configureBlocking(false);

        Selector selector = Selector.open();
        // server注册一个selector-监听的事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务启动成功...");

        while (true){
            // 事件的个数
            int num = selector.select(2000);
            if(num == 0){
                System.out.println("没有事件发生...");
                continue;
            }
            // 所有事件的集合
            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = keys.iterator();
            while (iterator.hasNext()){
                SelectionKey key = iterator.next();
                // 当客户端通道 调用connect(服务端)时，触发acceptable事件
                if(key.isAcceptable()){
                    // 得到客户端的通道-(客户端在connect的时候，会发生)
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    // 客户端的通道需要设置为非阻塞(*重要*)
                    socketChannel.configureBlocking(false);
                    System.out.println("有客户端连接...");
                    // 监听客户端的read事件
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }
                if(key.isReadable()){
                    // 得到客户端的通道
                    SocketChannel channel = (SocketChannel)key.channel();
                    ByteBuffer allocate = ByteBuffer.allocate(1024);
                    int read = channel.read(allocate);
                    if(read > 0){
                        System.out.println("客户端消息:" + new String(allocate.array(),0,read, StandardCharsets.UTF_8));
                        channel.write(ByteBuffer.wrap("没钱".getBytes(StandardCharsets.UTF_8)));
                        channel.close();
                    }
                }
                iterator.remove();
            }
        }
    }

}
